﻿using System;
using System.ComponentModel;
using System.Xml;
using System.Collections.Generic;
using System.Text;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Manager;
using System.Threading;

namespace PluginMeb
{
    public class ArtefactCache
    {
        /// <summary> The cached artefact </summary>
        private Artefact artefact;

        /// <summary> Date of update when artefact retrieved </summary>
        public DateTime DateLastUpdate { get; private set; }

        /// <summary> Indicates if artefact is reserved </summary>
        public bool IsLocked { get; private set; }

        /// <summary> Indicates if artefact content is updated </summary>
        public bool IsUpdated { get; private set; }

        private ArtefactRefTyped artefactIdentifier;


        public ArtefactCache(ArtefactRefTyped art)
        {
            artefactIdentifier = art;
            DateLastUpdate = DateTime.MinValue;
            IsLocked = false;
            IsUpdated = false;

            RefreshArtefact();
        }


        public Artefact MaintenableArtefact { get { return artefact; } }

        private bool RefreshArtefact()
        {
            bool IsNew = false;
            DirInfoHelper dirInfo = new DirInfoHelper(artefactIdentifier);
            DateTime dt = dirInfo.GetLastUpdateDate(artefactIdentifier.FullIdent);
            if (IsLocked == false && dt > DateLastUpdate)
            {
                SmManager sm = new SmManager();
                artefact = sm.GetArtefact(artefactIdentifier.Type, artefactIdentifier, true);
                if (artefact == null)
                    throw new ApplicationException("Unable to get artefact. " + artefactIdentifier.FullIdent);
                DateLastUpdate = dt;
                IsNew  = true;
            }

            return IsNew;
        }

        /// <summary>
        /// Cancel previous reservation on artefact
        /// </summary>
        public void CancelReservation()
        {
            if (IsLocked)
            {
                    SdmxMl.Multiplexor.Mux.Instance.UndoCheckOut(artefactIdentifier.Type.ToString(), 
                        artefactIdentifier.FullIdent);
                    IsLocked = false;
            }
        }

        /// <summary>
        /// Ensure cached content updated and reserve 
        /// </summary>
        public bool Reserve()
        {
            bool IsNew = RefreshArtefact();

            // And reserve
            SdmxMl.Multiplexor.Mux.Instance.CheckOut(artefactIdentifier.Type.ToString(),
                artefactIdentifier.FullIdent);
            IsLocked = true;
            return IsNew;
        }

        public void Persist()
        {
            if (IsLocked)
            {
                // Save in registry
                SmManager sm = new SmManager();
                sm.PutArtefact(artefactIdentifier.Type, artefact );
                XmlDocument xDoc = artefactIdentifier.Type == SdmxArtefactType.MetadataSet ?
                    sm.GetMetasetAsDocument(artefactIdentifier.FullIdent) : sm.GetAsDocument();
                SdmxMl.Multiplexor.Mux.Instance.SubmitArtefact(artefactIdentifier.Type.ToString(), artefactIdentifier.FullIdent, xDoc);
                
                IsLocked = false;

                // Update date last modif
                DirInfoHelper dirInfo = new DirInfoHelper(artefactIdentifier);
                DateLastUpdate = dirInfo.GetLastUpdateDate(artefactIdentifier.FullIdent);
            }
            else
                throw new ApplicationException("Artefact not reserved: " + artefactIdentifier.FullIdent);
        }

        public void UpdateContent(Artefact a)
        {
            if (a != null && a.ArType == artefact.ArType && a.FullIdent == artefactIdentifier.FullIdent)
                artefact = a;
            else
                throw new ApplicationException("Invalide update request for " + artefactIdentifier.FullIdent);

        }

    }
}

